package com.fneuch.game.minis.w40k.rules.engines;

import com.fneuch.game.Probability;
import com.fneuch.game.dice.Dice;
import com.fneuch.game.dice.DiceProbability;
import com.fneuch.game.minis.AttackResult;
import com.fneuch.game.minis.DefenderStatsProfile;
import com.fneuch.game.minis.ShooterStatsProfile;
import com.fneuch.game.minis.ShootingEngine;

public class W40kShootingEngine implements ShootingEngine {
	private static int[][] woundChart = {
			{4, 5, 6, 6,-1,-1,-1,-1,-1,-1}, // Strength 1
			{3, 4, 5, 6, 6,-1,-1,-1,-1,-1}, // Strength 2
			{2, 3, 4, 5, 6, 6,-1,-1,-1,-1}, // Strength 3
			{2, 2, 3, 4, 5, 6, 6,-1,-1,-1}, // Strength 4
			{2, 2, 2, 3, 4, 5, 6, 6,-1,-1}, // Strength 5
			{2, 2, 2, 2, 3, 4, 5, 6, 6,-1}, // Strength 6
			{2, 2, 2, 2, 2, 3, 4, 5, 6, 6}, // Strength 7
			{2, 2, 2, 2, 2, 2, 3, 4, 5, 6}, // Strength 8
			{2, 2, 2, 2, 2, 2, 2, 3, 4, 5}, // Strength 9
			{2, 2, 2, 2, 2, 2, 2, 2, 3, 4}, // Strength 10
	};

	Probability probability = new DiceProbability(Dice.D6);
	
	@Override
	public int toHit(int statsValue) {
		int result = 0;
		
		if(statsValue < 6) {
			result = probability.over(7-statsValue);
		}else{
			int underResult = probability.over(2);
			int overMaxValue = statsValue -6;
			int rerollResult = probability.over(6-overMaxValue);
			result = underResult + (100-underResult)*rerollResult/100;
		}
		
		return result;
	}

	@Override
	public int toWound(int strengthValue, int toughnessValue) {
		int retour = 0;
		int strengthNeeded = strengthValue-1 < 0 ? 0 : strengthValue-1;
		int toughnessNeeded = toughnessValue-1 < 0 ? 0 : toughnessValue-1;
		int statsNeeded = woundChart[strengthNeeded][toughnessNeeded];
		if(statsNeeded > 0) {
			retour = probability.over(statsNeeded); 
		}
		
		return retour;
	}

	@Override
	public int toSave(int saveValue) {
		return probability.over(saveValue);
	}

	@Override
	public AttackResult shoot(int nbShooter, ShooterStatsProfile shooter, int nbDefenders, DefenderStatsProfile defender) {
		AttackResult result = new AttackResult();
		
		result.setNbAttacks(nbShooter);
		double toHitPercent = toHit(shooter.getBallisticSkill());
		result.setToHit((int)toHitPercent);
		result.setNbHits((int)Math.round(nbShooter * toHitPercent/100));
		double toWoundPercent = toWound(shooter.getStrength(), defender.getToughness()); 
		result.setToWound((int)toWoundPercent);
		result.setNbWounded((int)Math.round(result.getNbHits() * toWoundPercent/100));
		double toSavePercent = toSave(defender.getSave()); 
		result.setToSave((int)toSavePercent);
		result.setNbSaved((int)Math.round(result.getNbWounded() * toSavePercent/100));
		int damaged = result.getNbWounded()- result.getNbSaved();
		result.setNbDefenderLeft(nbDefenders - damaged);
		return result;
	}

}
